LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

-- OutMUX
-- 
-- Move information between forwarding and transmit.
-- 
-- Inputs						Outputs
--
-- clk (1 bit)					FWD_to_XMT0_ACK  (1 bit)
-- reset (1 bit)				FWD_to_XMT1_ACK  (1 bit)
-- buffer0_data (8 bits)		FWD_to_XMT2_ACK  (1 bit)
-- buffer0_size (11 bits)		FWD_to_XMT3_ACK  (1 bit)
-- buffer0_done (1 bit)			FWD_to_XMT0_Data (8 bits)
-- buffer1_data (8 bits)		FWD_to_XMT1_Data (8 bits)
-- buffer1_size (11 bits)		FWD_to_XMT2_Data (8 bits)
-- buffer1_done (1 bit)			FWD_to_XMT3_Data (8 bits)
-- buffer2_data (8 bits)		FWD_to_XMT0_Size (11 bits)
-- buffer2_size (11 bits)		FWD_to_XMT1_Size (11 bits)
-- buffer2_done (1 bit)			FWD_to_XMT2_Size (11 bits)
-- buffer3_data (8 bits)		FWD_to_XMT3_Size (11 bits)
-- buffer3_size (11 bits)		FWD_to_XMT0_Done (1 bit)
-- buffer3_done (1 bit)			FWD_to_XMT1_Done (1 bit)
-- XMT0_size (11 bits)			FWD_to_XMT2_Done (1 bit)
-- XMT1_size (11 bits)			FWD_to_XMT3_Done (1 bit)
-- XMT2_size (11 bits)
-- XMT3_size (11 bits)
-- TBL_to_FWD_Valid	(1 bit)
-- TBL_to_FWD_Port (3 bits)
-- ARB_to_OMX_Port (2 bits)
-- ARB_to_OMX_Valid (1 bit)


ENTITY OutMUX IS
   PORT(
       
		clk, reset : IN STD_LOGIC;
		buffer0_data, buffer1_data, buffer2_data, buffer3_data : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
		buffer0_size, buffer1_size, buffer2_size, buffer3_size : IN STD_LOGIC_VECTOR(10 DOWNTO 0);
	    buffer0_done, buffer1_done, buffer2_done, buffer3_done : IN STD_LOGIC;
	    srcAddressValid0, srcAddressValid1, srcAddressValid2, srcAddressValid3 : IN STD_LOGIC;
	    desAddressValid0, desAddressValid1, desAddressValid2, desAddressValid3 : IN STD_LOGIC;
		TBL_to_FWD_ACK : IN STD_LOGIC;
		TBL_to_FWD_Valid : IN STD_LOGIC;
		ARB_to_OMX_Port : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
		ARB_to_OMX_Valid : IN STD_LOGIC;
		TBL_to_FWD_Port : IN STD_LOGIC_VECTOR(2 DOWNTO 0);		
		XMT0_size, XMT1_size, XMT2_size, XMT3_size : IN STD_LOGIC_VECTOR(10 DOWNTO 0);
		buffer0_request, buffer1_request, buffer2_request, buffer3_request : OUT STD_LOGIC;
		FWD_to_XMT0_ACK, FWD_to_XMT1_ACK, FWD_to_XMT2_ACK, FWD_to_XMT3_ACK : OUT STD_LOGIC;
		FWD_to_XMT0_Data, FWD_to_XMT1_Data, FWD_to_XMT2_Data, FWD_to_XMT3_Data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
		FWD_to_XMT0_Size, FWD_to_XMT1_Size, FWD_to_XMT2_Size, FWD_to_XMT3_Size : OUT STD_LOGIC_VECTOR(11 DOWNTO 0);
		FWD_to_XMT0_Done, FWD_to_XMT1_Done, FWD_to_XMT2_Done, FWD_to_XMT3_Done : OUT STD_LOGIC;
		bufferAlmostDone0, bufferAlmostDone1, bufferAlmostDone2, bufferAlmostDone3 : IN STD_LOGIC;
		OMX_to_ARB_Done : OUT STD_LOGIC
		
       );
END OutMux;

ARCHITECTURE outmux_arch OF OutMUX IS


COMPONENT ForwardingDecoder IS
	PORT
	(
		data		: IN STD_LOGIC_VECTOR (2 DOWNTO 0);
		eq00		: OUT STD_LOGIC ;
		eq01		: OUT STD_LOGIC ;
		eq02		: OUT STD_LOGIC ;
		eq03		: OUT STD_LOGIC ;
		eq04		: OUT STD_LOGIC ;
		eq05		: OUT STD_LOGIC ;
		eq06		: OUT STD_LOGIC ;
		eq07		: OUT STD_LOGIC 
	);
END COMPONENT;

-- 8 bit wide 4-way mux for moving data around
COMPONENT MUX8bit4way IS
	PORT
	(
		data0x		: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
		data1x		: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
		data2x		: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
		data3x		: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
		sel			: IN STD_LOGIC_VECTOR (1 DOWNTO 0);
		result		: OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
	);
END COMPONENT;


-- 11 bit wide 4-way mux for moving packet sizes around
COMPONENT MUX11bit4way IS
	PORT
	(
		data0x		: IN STD_LOGIC_VECTOR (11 DOWNTO 0);
		data1x		: IN STD_LOGIC_VECTOR (11 DOWNTO 0);
		data2x		: IN STD_LOGIC_VECTOR (11 DOWNTO 0);
		data3x		: IN STD_LOGIC_VECTOR (11 DOWNTO 0);
		sel			: IN STD_LOGIC_VECTOR (1 DOWNTO 0);
		result		: OUT STD_LOGIC_VECTOR (11 DOWNTO 0)
	);
END COMPONENT;

-- Shift Register to hold current srcPort from arbiter
COMPONENT srcPortShiftRegister IS
	PORT
	(
		aclr		: IN STD_LOGIC ;
		clock		: IN STD_LOGIC ;
		data		: IN STD_LOGIC_VECTOR (1 DOWNTO 0);
		enable		: IN STD_LOGIC ;
		load		: IN STD_LOGIC ;
		q		: OUT STD_LOGIC_VECTOR (1 DOWNTO 0)
	);
END COMPONENT;


COMPONENT srcPortLatch IS
	PORT
	(
		aclr		: IN STD_LOGIC ;
		data		: IN STD_LOGIC_VECTOR (1 DOWNTO 0);
		gate		: IN STD_LOGIC ;
		q		: OUT STD_LOGIC_VECTOR (1 DOWNTO 0)
	);
END COMPONENT;

COMPONENT desPortShiftRegister IS
	PORT
	(
		aclr		: IN STD_LOGIC ;
		clock		: IN STD_LOGIC ;
		data		: IN STD_LOGIC_VECTOR (2 DOWNTO 0);
		enable		: IN STD_LOGIC ;
		load		: IN STD_LOGIC ;
		q		: OUT STD_LOGIC_VECTOR (2 DOWNTO 0)
	);
END COMPONENT;

COMPONENT Invert12 IS
   PORT(
		hurr : IN STD_LOGIC_VECTOR(11 DOWNTO 0);
		durr : OUT STD_LOGIC_VECTOR(11 DOWNTO 0)
       );
END COMPONENT;

COMPONENT PacketSizer IS
   PORT(
        srcPort : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
        buffer0, buffer1, buffer2, buffer3 : IN STD_LOGIC_VECTOR(11 DOWNTO 0);
		output : OUT STD_LOGIC_VECTOR(11 DOWNTO 0)
       );
END COMPONENT;

COMPONENT PacketDataer IS
   PORT(
        srcPort : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
        buffer0, buffer1, buffer2, buffer3 : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
		output : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
       );
END COMPONENT;


COMPONENT CLA12 IS
	PORT( a,b				:IN 	STD_LOGIC_VECTOR(11 DOWNTO 0);
		  output			:OUT	STD_LOGIC_VECTOR(11 DOWNTO 0));
END COMPONENT;

COMPONENT packet_reg IS
	PORT(
		aclr		: IN STD_LOGIC ;
		clock		: IN STD_LOGIC ;
		data		: IN STD_LOGIC_VECTOR (11 DOWNTO 0);
		enable		: IN STD_LOGIC ;
		load		: IN STD_LOGIC ;
		q		: OUT STD_LOGIC_VECTOR (11 DOWNTO 0)
	);
END COMPONENT;

COMPONENT OUTdatalatch IS
	PORT
	(
		data		: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
		gate		: IN STD_LOGIC ;
		q		: OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
	);
END COMPONENT;

COMPONENT BufferFIFO IS
	PORT
	(
		aclr		: IN STD_LOGIC ;
		clock		: IN STD_LOGIC ;
		data		: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
		rdreq		: IN STD_LOGIC ;
		wrreq		: IN STD_LOGIC ;
		empty		: OUT STD_LOGIC ;
		full		: OUT STD_LOGIC ;
		q			: OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
		usedw		: OUT STD_LOGIC_VECTOR (10 DOWNTO 0)
	);
END COMPONENT;

COMPONENT TestFF IS
	PORT
	(
		aclr		: IN STD_LOGIC ;
		clock		: IN STD_LOGIC ;
		data		: IN STD_LOGIC ;
		q		: OUT STD_LOGIC 
	);
END COMPONENT;

COMPONENT OutMUXReadyFF IS
	PORT
	(
		aclr		: IN STD_LOGIC ;
		aset		: IN STD_LOGIC ;
		clock		: IN STD_LOGIC ;
		data		: IN STD_LOGIC ;
		enable		: IN STD_LOGIC ;
		q		: OUT STD_LOGIC 
	);
END COMPONENT;

COMPONENT OutMUXFlipFlop IS
	PORT
	(
		aclr		: IN STD_LOGIC ;
		clock		: IN STD_LOGIC ;
		data		: IN STD_LOGIC ;
		enable		: IN STD_LOGIC ;
		q		: OUT STD_LOGIC 
	);
END COMPONENT;

SIGNAL desPort : STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL srcPort : STD_LOGIC_VECTOR(1 DOWNTO 0);
SIGNAL dataSignal : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL addrSignal : STD_LOGIC_VECTOR(11 DOWNTO 0);
SIGNAL difference0, difference1, difference2, difference3 : STD_LOGIC_VECTOR(11 DOWNTO 0);
SIGNAL padsize0, padsize1, padsize2, padsize3 : STD_LOGIC_VECTOR(11 DOWNTO 0);
SIGNAL ipadsize0, ipadsize1, ipadsize2, ipadsize3 : STD_LOGIC_VECTOR(11 DOWNTO 0);
SIGNAL padXMTSize0, padXMTSize1, padXMTSize2, padXMTSize3 : STD_LOGIC_VECTOR(11 DOWNTO 0);
SIGNAL XMT0hasSpace, XMT1hasSpace, XMT2hasSpace, XMT3hasSpace : STD_LOGIC;
SIGNAL XMTisReady : STD_LOGIC;
SIGNAL packetSize : STD_LOGIC_VECTOR(11 DOWNTO 0);
SIGNAL packetSizeOut0, packetSizeOut1, packetSizeOut2, packetSizeOut3: STD_LOGIC_VECTOR(11 DOWNTO 0);
SIGNAL packetData : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL output0, output1, output2, output3 : STD_LOGIC;
SIGNAL override0, override1, override2, override3 : STD_LOGIC;
SIGNAL padsizeinput0, padsizeinput1, padsizeinput2, padsizeinput3 : STD_LOGIC_VECTOR(11 DOWNTO 0);
SIGNAL ACK0, ACK1, ACK2, ACK3:  STD_LOGIC;
SIGNAL outBuffEmpty0,outBuffEmpty1,outBuffEmpty2,outBuffEmpty3 : STD_LOGIC; 
SIGNAL outBuffFull0,outBuffFull1,outBuffFull2,outBuffFull3 : STD_LOGIC;
SIGNAL outBuffLength0,outBuffLength1,outBuffLength2,outBuffLength3: STD_LOGIC_VECTOR(10 DOWNTO 0);
SIGNAL outbufferisDone0,outbufferisDone1,outbufferisDone2,outbufferisDone3 : STD_LOGIC;
SIGNAL packetdataout : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL buffer0_ready, buffer1_ready, buffer2_ready, buffer3_ready : STD_LOGIC;
SIGNAL ACKSignal0, ACKSignal1, ACKSignal2, ACKSignal3 : STD_LOGIC;
SIGNAL selectedbufferisempty : STD_LOGIC;
SIGNAL onlydoonce0, onlydoonce1, onlydoonce2, onlydoonce3 : STD_LOGIC;
SIGNAL throwlastXMTthing0, throwlastXMTthing1, throwlastXMTthing2, throwlastXMTthing3 : STD_LOGIC;
SIGNAL FWD_to_XMT0_ACK_signal, FWD_to_XMT1_ACK_signal, FWD_to_XMT2_ACK_signal, FWD_to_XMT3_ACK_signal :STD_LOGIC;
SIGNAL buffer0ready, buffer1ready, buffer2ready, buffer3ready : STD_LOGIC;
SIGNAL buffer0_request_signal : STD_LOGIC;
SIGNAL Latched_TBL_to_FWD_Valid : STD_LOGIC;
SIGNAL wewerereading : STD_LOGIC;
SIGNAL buffer0cango, buffer1cango, buffer2cango, buffer3cango : STD_LOGIC;
SIGNAL selectedbuffercango : STD_LOGIC;
SIGNAL selectedbufferisemptysignal : STD_LOGIC;

SIGNAL OMX_to_ARB_Done_Signal : STD_LOGIC;

BEGIN
--
---- Get the new srcPort from the arbiter, assuming no conflicts with anything
GetSrcPort: srcPortShiftRegister PORT MAP(reset, clk, ARB_to_OMX_Port, ARB_to_OMX_Valid, '1', srcPort);
---- Get the new desPort from the table
GetDesPort: desPortShiftRegister PORT MAP(reset, clk, TBL_to_FWD_Port, TBL_to_FWD_Valid, '1', desPort); 
--
---- Latch high if we've received a valid address from the table and if we still have data in our data buffer.
---- This gets passed on to the requests to the buffers so that we aren't magically grabbing data.

selectedbufferisempty <= buffer0ready OR buffer1ready OR buffer2ready OR buffer3ready;
buffer0ready <= (buffer0_done AND (NOT(srcPort(0)) AND NOT(srcPort(1))));
buffer1ready <= (buffer1_done AND ((srcPort(0)) AND NOT(srcPort(1))));
buffer2ready <= (buffer2_done AND ((srcPort(1)) AND NOT(srcPort(0))));
buffer3ready <= (buffer3_done AND ((srcPort(0)) AND (srcPort(1))));

selectedbuffercango <= buffer0cango OR buffer1cango OR buffer2cango OR buffer3cango;
buffer0cango <= (NOT((srcAddressValid0)) AND (NOT(srcPort(0)) AND NOT(srcPort(1))));
buffer1cango <= (NOT((srcAddressValid1)) AND ((srcPort(0)) AND NOT(srcPort(1))));
buffer2cango <= (NOT((srcAddressValid2)) AND ((srcPort(1)) AND NOT(srcPort(0))));
buffer3cango <= (NOT((srcAddressValid3)) AND ((srcPort(0)) AND (srcPort(1))));





LatchTBL_to_FWD_Valid: TestFF PORT MAP(reset,clk, TBL_to_FWD_Valid, Latched_TBL_to_FWD_Valid );

-- Something is wrong here
-- If arbiter requests a buffer to be read
-- If table gives us a destination
-- Request data from that buffer until it is empty (Failing)
-- Reset when we say to
GetReady0: OutMUXReadyFF PORT MAP(reset OR (buffer0_done AND (NOT(srcPort(0)) AND NOT(srcPort(1)))), TBL_to_FWD_Valid AND NOT((srcPort(0) OR srcPort(1))), clk, '0', '0', buffer0_request);
GetReady1: OutMUXReadyFF PORT MAP(reset OR (buffer1_done AND ((srcPort(0)) AND NOT(srcPort(1)))), TBL_to_FWD_Valid AND (srcPort(0) AND NOT(srcPort(1))), clk, '0', '0', buffer1_request);
GetReady2: OutMUXReadyFF PORT MAP(reset OR (buffer2_done AND ((srcPort(1)) AND NOT(srcPort(0)))), TBL_to_FWD_Valid AND (srcPort(1) AND NOT(srcPort(0))), clk, '0', '0', buffer2_request);
GetReady3: OutMUXReadyFF PORT MAP(reset OR (buffer3_done AND ((srcPort(0)) AND (srcPort(1)))), TBL_to_FWD_Valid AND (srcPort(0) AND srcPort(1)), clk, '0', '0', buffer3_request);
--
--
---- Extend the size of the packet to 12 bits
padsize0(10 DOWNTO 0) <= buffer0_size;
padsize1(10 DOWNTO 0) <= buffer1_size;
padsize2(10 DOWNTO 0) <= buffer2_size;
padsize3(10 DOWNTO 0) <= buffer3_size;
--
--
--OMX_to_ARB_Done <= '0';
-- OMX to ARB Done goes low only when the selectedbufferisnotempty and doesn't go high until we receive a 
-- full frame.

--selectedbufferisempty <= buffer0ready OR buffer1ready OR buffer2ready OR buffer3ready;
--buffer0ready <= (buffer0_done AND (NOT(srcPort(0)) AND NOT(srcPort(1))));
--buffer1ready <= (buffer1_done AND ((srcPort(0)) AND NOT(srcPort(1))));
--buffer2ready <= (buffer2_done AND ((srcPort(1)) AND NOT(srcPort(0))));
--buffer3ready <= (buffer3_done AND ((srcPort(0)) AND (srcPort(1))));

--	    srcAddressValid0, srcAddressValid1, srcAddressValid2, srcAddressValid3 : IN STD_LOGIC;
--	    desAddressValid0, desAddressValid1, desAddressValid2, desAddressValid3 : IN STD_LOGIC;

-- Latch selectedbufferisempty and then reset it when we see selectedbuffercango

--Latchtheselectedbufferisempty: OutMUXFlipFlop PORT MAP(reset, clk, selectedbufferisempty, NOT(selectedbufferisempty) OR (selectedbuffercango), selectedbufferisemptysignal);


LatchOtAD: OutMUXFlipFlop PORT MAP(reset, clk, selectedbufferisempty , selectedbufferisempty OR TBL_to_FWD_ACK, OMX_to_ARB_Done_Signal);

--COMPONENT OutMUXFlipFlop IS
--	PORT
--	(
--		aclr		: IN STD_LOGIC ;
--		clock		: IN STD_LOGIC ;
--		data		: IN STD_LOGIC ;
--		enable		: IN STD_LOGIC ;
--		q		: OUT STD_LOGIC 
--	);
--END COMPONENT;


--OMX_to_ARB_Done <= selectedbufferisempty;
OMX_to_ARB_Done <= OMX_to_ARB_Done_Signal;
--wewerereading<= ;
--

-- OMX_to_ARB_Done is high if:
-- The buffer we were reading from is empty for the first time
-- and we were reading from it previously.

---- Based on that source port, open up the muxes at the beginning for data and address
OpenDataMUXes: MUX8bit4way PORT MAP(buffer0_data, buffer1_data, buffer2_data, buffer3_data, srcPort, dataSignal); 
OpenAddrMUXes: MUX11bit4way PORT MAP(padsize0, padsize1, padsize2, padsize3, srcPort, addrSignal );
--
--
---- Now that you have the srcPort and the desPort and all the associated data, check which ports have space available
---- Pretty goddamn 1337
--
---- TODO: Put the size of the packet to be sent into a register, because the one from buffer is going to be decreasing
---- over time and because XMT is too lazy to use a register to hold the value and save us both some time.
packetRegister1: packet_reg PORT MAP(reset, clk, packetSize, TBL_to_FWD_Valid, '1',packetSizeOut0);
packetRegister2: packet_reg PORT MAP(reset, clk, packetSize, TBL_to_FWD_Valid, '1',packetSizeOut1);
packetRegister3: packet_reg PORT MAP(reset, clk, packetSize, TBL_to_FWD_Valid, '1',packetSizeOut2);
packetRegister4: packet_reg PORT MAP(reset, clk, packetSize, TBL_to_FWD_Valid, '1',packetSizeOut3);
--
FWD_to_XMT0_Size<=packetSizeOut0;
FWD_to_XMT1_Size<=packetSizeOut1;
FWD_to_XMT2_Size<=packetSizeOut2;
FWD_to_XMT3_Size<=packetSizeOut3;
--
---- Extend the space available signal to 12 bits
padXMTSize0(10 DOWNTO 0) <= XMT0_size;
padXMTSize1(10 DOWNTO 0) <= XMT1_size;
padXMTSize2(10 DOWNTO 0) <= XMT2_size;
padXMTSize3(10 DOWNTO 0) <= XMT3_size;
--
--
---- Negate the size of the packet
InvertSize0: Invert12 PORT MAP(padsize0, ipadsize0);
InvertSize1: Invert12 PORT MAP(padsize1, ipadsize1);
InvertSize2: Invert12 PORT MAP(padsize2, ipadsize2);
InvertSize3: Invert12 PORT MAP(padsize3, ipadsize3);
--
--
---- Add XMT's space available from the inverse of the size of the packet
DoMath0: CLA12 PORT MAP(ipadsize0, padXMTSize0, difference0);
DoMath1: CLA12 PORT MAP(ipadsize1, padXMTSize1, difference1);
DoMath2: CLA12 PORT MAP(ipadsize2, padXMTSize2, difference2);
DoMath3: CLA12 PORT MAP(ipadsize3, padXMTSize3, difference3);
--
--
---- If the answer is negative, the packet is larger than space available. The inverse of that shows whether or not
---- the packet is smaller than the space available.
XMT0hasSpace <= NOT(difference0(11));
XMT1hasSpace <= NOT(difference1(11));
XMT2hasSpace <= NOT(difference2(11));
XMT3hasSpace <= NOT(difference3(11));
--
--
---- We're serializing everything, so check if all the ports have space.
XMTisReady <= XMT0hasSpace AND XMT1hasSpace AND XMT2hasSpace AND XMT3hasSpace;
--
padsizeinput0(10 DOWNTO 0) <= buffer0_size;
padsizeinput1(10 DOWNTO 0) <= buffer1_size;
padsizeinput2(10 DOWNTO 0) <= buffer2_size;
padsizeinput3(10 DOWNTO 0) <= buffer3_size;
--
---- Determine which packet data and size we're reporting.
GetPacketSize: PacketSizer PORT MAP (srcPort, padsizeinput0, padsizeinput1, padsizeinput2, padsizeinput3, packetSize);
GetPacketData: PacketDataer PORT MAP (srcPort, buffer0_data, buffer1_data, buffer2_data, buffer3_data, packetData);
--
---- TODO: Include logic so that FWD_to_XMT0 is the packetSize from the first cycle, and not zero.
---- **** think this was accomplished aboved with packetRegister
----FWD_to_XMT0_Size(10 DOWNTO 0) <= packetSize;
----FWD_to_XMT1_Size(10 DOWNTO 0) <= packetSize;
--
----Buffer to read in the data from Forwarding Buffer
---- Wat
----buffer_fifo1: BufferFIFO PORT MAP (reset, clk, packetData, ACK0, '1', outBuffEmpty0, outBuffFull0, FWD_to_XMT0_Data, outBuffLength0);
----buffer_fifo2: BufferFIFO PORT MAP (reset, clk, packetData, ACK1, '1', outBuffEmpty1, outBuffFull1, FWD_to_XMT1_Data, outBuffLength1);
----buffer_fifo3: BufferFIFO PORT MAP (reset, clk, packetData, ACK2, '1', outBuffEmpty2, outBuffFull2, FWD_to_XMT2_Data, outBuffLength2);
----buffer_fifo4: BufferFIFO PORT MAP (reset, clk, packetData, ACK3, '1', outBuffEmpty3, outBuffFull3, FWD_to_XMT3_Data, outBuffLength3);
--
--
FWD_to_XMT0_Data <= packetData;
FWD_to_XMT1_Data <= packetData;
FWD_to_XMT2_Data <= packetData;
FWD_to_XMT3_Data <= packetData;

DecodeCrap: ForwardingDecoder PORT MAP (desPort, output0, output1, output2, output3, override0, override1, override2, override3);

--COMPONENT OutMUXFlipFlop IS
--	PORT
--	(
--		aclr		: IN STD_LOGIC ;
--		clock		: IN STD_LOGIC ;
--		data		: IN STD_LOGIC ;
--		enable		: IN STD_LOGIC ;
--		q		: OUT STD_LOGIC 
--	);
--END COMPONENT;


-- How do we ACK once at the end of the frame?
-- buffer0_Done indicates that the count is now zero.
DoOutMUXFlipFlop0: OutMUXFlipFlop PORT MAP (reset, clk, bufferAlmostDone0, '1', ACKSignal0);
DoOutMUXFlipFlop1: OutMUXFlipFlop PORT MAP (reset, clk, bufferAlmostDone1, '1', ACKSignal1);
DoOutMUXFlipFlop2: OutMUXFlipFlop PORT MAP (reset, clk, bufferAlmostDone2, '1', ACKSignal2);
DoOutMUXFlipFlop3: OutMUXFlipFlop PORT MAP (reset, clk, bufferAlmostDone3, '1', ACKSignal3);



--ENTITY OutMUXReadyFF IS
--	PORT
--	(
--		aclr		: IN STD_LOGIC ;
--		aset		: IN STD_LOGIC ;
--		clock		: IN STD_LOGIC ;
--		data		: IN STD_LOGIC ;
--		enable		: IN STD_LOGIC ;
--		q		: OUT STD_LOGIC 
--	);
--END OutMUXReadyFF;

-- onlydoonce0, onlydoonce1, onlydoonce2, onlydoonce3
-- throwlastXMTthing0, throwlastXMTthing1, throwlastXMTthing2, throwlastXMTthing3

CheckOnlyOnce0: OutMUXReadyFF PORT MAP(reset, '0', clk, selectedbufferisempty, '1', onlydoonce0);
throwlastXMTthing0 <= (NOT(onlydoonce0) AND selectedbufferisempty);

CheckOnlyOnce1: OutMUXReadyFF PORT MAP(reset, '0', clk, selectedbufferisempty, '1', onlydoonce1);
throwlastXMTthing1 <= (NOT(onlydoonce1) AND selectedbufferisempty);

CheckOnlyOnce2: OutMUXReadyFF PORT MAP(reset, '0', clk, selectedbufferisempty, '1', onlydoonce2);
throwlastXMTthing2 <= (NOT(onlydoonce2) AND selectedbufferisempty);

CheckOnlyOnce3: OutMUXReadyFF PORT MAP(reset, '0', clk, selectedbufferisempty, '1', onlydoonce3);
throwlastXMTthing3 <= (NOT(onlydoonce3) AND selectedbufferisempty);



--DoOncething0: OutMUXReadyFF PORT MAP (reset, '0', clk, NOT(onlydoonce0stop), selectedbufferisempty AND NOT(onlydoonce0), onlydoonce0);
--DoOnceStepTwo0: OutMUXReadyFF PORT MAP(reset, '0', clk, NOT(onlydoonce0), NOT(onlydoonce0stop), onlydoonce0stop);
--DoOncething1: OutMUXReadyFF PORT MAP (reset, '0', clk, NOT(onlydoonce1stop), selectedbufferisempty AND NOT(onlydoonce1), onlydoonce1);
--DoOnceStepTwo1: OutMUXReadyFF PORT MAP(reset, '0', clk, NOT(onlydoonce1), NOT(onlydoonce1stop), onlydoonce1stop);
--DoOncething2: OutMUXReadyFF PORT MAP (reset, '0', clk, NOT(onlydoonce2stop), selectedbufferisempty AND NOT(onlydoonce2), onlydoonce2);
--DoOnceStepTwo2: OutMUXReadyFF PORT MAP(reset, '0', clk, NOT(onlydoonce2), NOT(onlydoonce2stop), onlydoonce2stop);
--DoOncething3: OutMUXReadyFF PORT MAP (reset, '0', clk, NOT(onlydoonce3stop), selectedbufferisempty AND NOT(onlydoonce3), onlydoonce3);
--DoOnceStepTwo3: OutMUXReadyFF PORT MAP(reset, '0', clk, NOT(onlydoonce3), NOT(onlydoonce3stop), onlydoonce3stop);

FWD_to_XMT0_ACK_signal <= ((Latched_TBL_to_FWD_Valid OR (throwlastXMTthing0)) AND (output0 OR override0 OR override1 OR override2 OR override3));
FWD_to_XMT1_ACK_signal <= ((Latched_TBL_to_FWD_Valid OR (throwlastXMTthing1)) AND (output1 OR override0 OR override1 OR override2 OR override3));
FWD_to_XMT2_ACK_signal <= ((Latched_TBL_to_FWD_Valid OR (throwlastXMTthing2)) AND (output2 OR override0 OR override1 OR override2 OR override3));
FWD_to_XMT3_ACK_signal <= ((Latched_TBL_to_FWD_Valid OR (throwlastXMTthing3)) AND (output3 OR override0 OR override1 OR override2 OR override3));
--
--COMPONENT TestFF IS
--	PORT
--	(
--		aclr		: IN STD_LOGIC ;
--		clock		: IN STD_LOGIC ;
--		data		: IN STD_LOGIC ;
--		q		: OUT STD_LOGIC 
--	);
--END COMPONENT;

Delay_XMT0_ACK : TestFF PORT MAP (reset, clk, FWD_to_XMT0_ACK_signal, FWD_to_XMT0_ACK);
Delay_XMT1_ACK : TestFF PORT MAP (reset, clk, FWD_to_XMT1_ACK_signal, FWD_to_XMT1_ACK);
Delay_XMT2_ACK : TestFF PORT MAP (reset, clk, FWD_to_XMT2_ACK_signal, FWD_to_XMT2_ACK);
Delay_XMT3_ACK : TestFF PORT MAP (reset, clk, FWD_to_XMT3_ACK_signal, FWD_to_XMT3_ACK);


---- ACK is used instead of FWD_to_XMTX_ACK because it's an internal signal, not an output
---- Determines on which ports data will be sent out
ACK0 <= output0 OR override0 OR override1 OR override2 OR override3;
ACK1 <= output1 OR override0 OR override1 OR override2 OR override3;
ACK2 <= output2 OR override0 OR override1 OR override2 OR override3;
ACK3 <= output3 OR override0 OR override1 OR override2 OR override3;
--
---- Send the done signals if you receive them from the buffer
Signalbuffer0: TestFF PORT MAP (reset, clk, outBuffEmpty0, outbufferisDone0);
Signalbuffer1: TestFF PORT MAP (reset, clk, outBuffEmpty1, outbufferisDone1);
Signalbuffer2: TestFF PORT MAP (reset, clk, outBuffEmpty2, outbufferisDone2);
Signalbuffer3: TestFF PORT MAP (reset, clk, outBuffEmpty3, outbufferisDone3);
--
FWD_to_XMT0_Done <= buffer0_done;
FWD_to_XMT1_Done <= buffer1_done;
FWD_to_XMT2_Done <= buffer2_done;
FWD_to_XMT3_Done <= buffer3_done;


END outmux_arch;